package export;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.FileUtils;

import util.StringUtils;

public class Generator {

	private String className = null;
	private String packageName = null;
	private String exportPath = null;

	/**
	 * Default constructor.
	 */
	public Generator(String className, String packageName, String exportPath) {
		super();
		if (className == null || exportPath == null || className.length() <= 0
				|| exportPath.length() <= 0) {
			throw new IllegalArgumentException("Illegal Argument");
		}
		if (!exportPath.endsWith(File.separator)) {
			exportPath = exportPath.concat(File.separator);
		}
		if (packageName == null) {
			packageName = "";
		}
		this.className = className;
		this.exportPath = exportPath;
		this.packageName = packageName;
	}

	/**
	 * Is Any Output File Existed
	 * 
	 * @return boolean
	 */
	public boolean isAnyOutputFileExisted() {
		if (new File(exportPath.concat("JDBMapLite.xml")).exists()) {
			return true;
		}
		if (new File(exportPath.concat(className.concat("Dao.xml"))).exists()) {
			return true;
		}
		if (new File(exportPath.concat(className.concat(".java"))).exists()) {
			return true;
		}
		if (new File(exportPath.concat(className.concat("Dao.java"))).exists()) {
			return true;
		}
		return false;
	}

	/**
	 * Generate Global Setting File
	 * 
	 * @param isOverwrite
	 *            boolean
	 * @throws IOException
	 */
	public void generateGlobalSettingFile(boolean isOverwrite)
			throws IOException {
		File destFile = new File(exportPath.concat("JDBMapLite.xml"));
		if (!isOverwrite && destFile.exists()) {
			throw new IllegalAccessError("File existed");
		}
		String data = StringUtils.readFileToString("JDBMapLite.xml.template");
		FileUtils.writeStringToFile(destFile, data, "UTF-8");
	}

	/**
	 * Generate Sql Definition File
	 * 
	 * @param beanDefinitionList
	 *            List{BeanDefinition}
	 * @param isOverwrite
	 *            boolean
	 * @throws IOException
	 */
	public void generateSqlDefinitionFile(
			List<BeanDefinition> beanDefinitionList, boolean isOverwrite)
			throws IOException {
		File destFile = new File(exportPath.concat(className.concat("Dao.xml")));
		if (!isOverwrite && destFile.exists()) {
			throw new IllegalAccessError("File existed");
		}
		// to underline case
		List<String> underlineCaseColumnNameList = new ArrayList<String>();
		for (BeanDefinition beanDef : beanDefinitionList) {
			underlineCaseColumnNameList.add(StringUtils
					.camelCaseToUnderlineCase(beanDef.getName()));
		}
		String columnNames = org.apache.commons.lang.StringUtils.join(
				underlineCaseColumnNameList, ", ");
		String data = StringUtils.readFileToString("$1Dao.xml.template");
		String underlineCaseClassName = StringUtils
				.camelCaseToUnderlineCase(className);
		// format
		data = StringUtils.format(data, "$", className, underlineCaseClassName,
				columnNames);
		FileUtils.writeStringToFile(destFile, data, "UTF-8");
	}

	/**
	 * Generate Bean Definition File
	 * 
	 * @param beanDefinitionList
	 *            List{BeanDefinition}
	 * @param isOverwrite
	 *            boolean
	 * @throws IOException
	 */
	public void generateBeanDefinitionFile(
			List<BeanDefinition> beanDefinitionList, boolean isOverwrite)
			throws IOException {
		File destFile = new File(exportPath.concat(className.concat(".java")));
		if (!isOverwrite && destFile.exists()) {
			throw new IllegalAccessError("File existed");
		}
		String data = StringUtils.readFileToString("$1.java.template");
		// remove the comment
		data = data.replace("// package $2;",
				(packageName.length() > 0 ? "package $2;" : ""));
		boolean containsBeanDefinition = !beanDefinitionList.isEmpty();
		data = data.replace("\t// $3", (containsBeanDefinition ? "$3" : ""));
		data = data.replace("\t// $4", (containsBeanDefinition ? "$4" : ""));
		// declare, setter and getters
		List<String> declareLineList = new ArrayList<String>();
		List<String> functionLineList = new ArrayList<String>();
		for (BeanDefinition beanDef : beanDefinitionList) {
			// declare
			declareLineList.add(StringUtils.format("\tprivate $1 $2;", "$",
					beanDef.getType(), beanDef.getName()));
			// setter
			functionLineList.add(StringUtils.format(
					"\tpublic void set$1($2 $3) {\r\n\t\tthis.$3 = $3;\r\n\t}",
					"$", StringUtils.toTitleCase(beanDef.getName()),
					beanDef.getType(), beanDef.getName()));
			// getter
			functionLineList.add(StringUtils.format(
					"\tpublic $2 get$1() {\r\n\t\treturn $3;\r\n\t}", "$",
					StringUtils.toTitleCase(beanDef.getName()),
					beanDef.getType(), beanDef.getName()));
		}
		String declareLines = org.apache.commons.lang.StringUtils.join(
				declareLineList, "\r\n");
		String functionLines = org.apache.commons.lang.StringUtils.join(
				functionLineList, "\r\n\r\n");
		// format
		data = StringUtils.format(data, "$", className, packageName,
				declareLines, functionLines);
		FileUtils.writeStringToFile(destFile, data, "UTF-8");
	}

	/**
	 * Generate Dao Definition File
	 * 
	 * @param isOverwrite
	 *            boolean
	 * @throws IOException
	 */
	public void generateDaoDefinitionFile(boolean isOverwrite)
			throws IOException {
		File destFile = new File(
				exportPath.concat(className.concat("Dao.java")));
		if (!isOverwrite && destFile.exists()) {
			throw new IllegalAccessError("File existed");
		}
		String data = StringUtils.readFileToString("$1Dao.java.template");
		// remove the comment
		data = data.replace("// package $2;",
				(packageName.length() > 0 ? "package $2;" : ""));
		data = data.replace("// import $3;",
				(packageName.length() > 0 ? "import $3;" : ""));
		String lowerCaseClassName = StringUtils
				.upperCamelCaseToLowerCamelCase(className);
		// format
		data = StringUtils.format(data, "$", className, packageName,
				lowerCaseClassName);
		FileUtils.writeStringToFile(destFile, data, "UTF-8");
	}

}